package com.quant.strategy;

import com.quant.entity.StockDaily;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.Set;

/**
 * 均线交叉策略
 * 当短期均线上穿长期均线时买入，下穿时卖出
 * @author lulj
 */
@Data
@Component
@Slf4j
public class MACrossStrategy implements Strategy {
    private String name = "均线交叉策略";
    private int shortWindow = 10;  // 短期均线窗口
    private int longWindow = 30;   // 长期均线窗口
    private double positionRatio = 0.8;  // 仓位比例

	@Override
	public void init() {
		// 1. 参数有效性校验
		if (shortWindow <= 0 || longWindow <= 0) {
			throw new IllegalArgumentException("均线窗口大小必须为正数，当前短期窗口: " + shortWindow + ", 长期窗口: " + longWindow);
		}
		if (shortWindow >= longWindow) {
			throw new IllegalArgumentException("短期窗口必须小于长期窗口，当前短期窗口: " + shortWindow + ", 长期窗口: " + longWindow);
		}
		if (positionRatio <= 0 || positionRatio > 1.0) {
			throw new IllegalArgumentException("仓位比例必须在(0, 1]范围内，当前值: " + positionRatio);
		}

		// 2. 检查支持的均线窗口（与getMAValue方法中的支持列表对齐）
		Set<Integer> supportedWindows = Set.of(5, 10, 20, 30);
		if (!supportedWindows.contains(shortWindow)) {
			throw new IllegalArgumentException("不支持的短期均线窗口: " + shortWindow + "，支持的窗口为: " + supportedWindows);
		}
		if (!supportedWindows.contains(longWindow)) {
			throw new IllegalArgumentException("不支持的长期均线窗口: " + longWindow + "，支持的窗口为: " + supportedWindows);
		}

		// 3. 初始化日志记录
		log.info("均线交叉策略初始化完成");
		log.info("策略参数 - 短期窗口: {}天, 长期窗口: {}天, 仓位比例: {}%",
				shortWindow, longWindow, positionRatio * 100);
	}

    @Override
    public int generateSignal(List<StockDaily> dailyList, int index) {
        // 确保有足够的数据计算均线
        if (index < longWindow) {
            return 0;
        }

        StockDaily current = dailyList.get(index);
        StockDaily previous = dailyList.get(index - 1);

        // 获取对应的均线值
        double shortMA = getMAValue(current, shortWindow);
        double longMA = getMAValue(current, longWindow);
        double prevShortMA = getMAValue(previous, shortWindow);
        double prevLongMA = getMAValue(previous, longWindow);

        // 金叉: 短期均线上穿长期均线
        if (prevShortMA <= prevLongMA && shortMA > longMA) {
            return 1;  // 买入信号
        }

        // 死叉: 短期均线下穿长期均线
        if (prevShortMA >= prevLongMA && shortMA < longMA) {
            return -1;  // 卖出信号
        }

        return 0;  // 无信号
    }

    /**
     * 根据窗口大小获取对应的均线值
     */
    private double getMAValue(StockDaily daily, int window) {
        switch (window) {
            case 5: return daily.getMa5();
            case 10: return daily.getMa10();
            case 20: return daily.getMa20();
            case 30: return daily.getMa30();
            default: throw new IllegalArgumentException("不支持的均线窗口: " + window);
        }
    }
}
